/**
 * OCR图像处理模块
 */

// 使用OpenCV进行OCR识别
function ocrWithOpenCV(imageData, config) {
    return new Promise((resolve, reject) => {
        // 发送图像到Python后端进行OCR处理
        fetch('/api/ocr', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                image: imageData
            })
        })
        .then(response => response.json())
        .then(result => {
            if (result.success) {
                resolve(result.grid);
            } else {
                reject(new Error(result.error || 'OCR识别失败'));
            }
        })
        .catch(err => {
            reject(err);
        });
    });
}

// 使用Tesseract.js进行OCR识别
function ocrWithTesseract(imageData) {
    return new Promise((resolve, reject) => {
        // 显示识别状态
        updateStatusMessage('<i class="fas fa-circle-notch fa-spin mr-2"></i>正在使用Tesseract.js识别图片中的数独...', 'status-message text-blue-600 info-message');
        
        // 使用Tesseract.js识别图像
        Tesseract.recognize(
            imageData,
            'eng',
            { 
                logger: info => console.log(info),
                tessedit_char_whitelist: '123456789',
                preserve_interword_spaces: '1',
                page_separator: '',
                tessedit_pageseg_mode: Tesseract.PSM.SINGLE_BLOCK
            }
        ).then(({ data: { text, words } }) => {
            console.log('识别到的完整文本:', text);
            console.log('识别到的单词:', words);
            updateStatusMessage('<i class="fas fa-circle-notch fa-spin mr-2"></i>识别完成，正在解析数独...');
            // 解析识别到的文本并填充到数独棋盘
            parseSudokuFromTextWithPosition({ data: { words, text } }, imageData)
                .then(grid => {
                    resolve(grid);
                })
                .catch(err => {
                    reject(err);
                });
        }).catch(err => {
            console.error(err);
            // 提供更详细的错误信息
            let errorMessage = '识别失败';
            if (err.message) {
                errorMessage += ': ' + err.message;
            }
            updateStatusMessage('<i class="fas fa-exclamation-circle mr-2"></i>' + errorMessage + '，请重试', 'status-message text-red-600 error-message');
            reject(new Error(errorMessage));
        });
    });
}

// 从文本解析数独(带位置信息)
function parseSudokuFromTextWithPosition(result, imageData) {
    return new Promise((resolve, reject) => {
        // 初始化空白数独棋盘
        const sudoku = Array(9).fill().map(() => Array(9).fill(0));
        let recognizedDigits = 0;
        
        try {
            // 检查是否有有效的OCR结果
            if (result && result.data && result.data.words) {
                // 创建一个9x9的网格来存储识别到的数字
                const grid = Array(9).fill().map(() => Array(9).fill(null));
                const confidence = Array(9).fill().map(() => Array(9).fill(0)); // 用于存储置信度
                
                // 获取文本内容用于回退
                const text = result.data.text || "";
                
                // 创建一个图像元素来获取图像尺寸
                const img = new Image();
                
                img.onload = function() {
                    const imageWidth = img.naturalWidth || img.width;
                    const imageHeight = img.naturalHeight || img.height;
                    
                    // 计算每个单元格的尺寸
                    const cellWidth = imageWidth / 9;
                    const cellHeight = imageHeight / 9;
                    
                    console.log(`图像尺寸: ${imageWidth}x${imageHeight}, 单元格尺寸: ${cellWidth}x${cellHeight}`);
                    
                    // 遍历识别到的单词
                    result.data.words.forEach((word, index) => {
                        // 获取单词的文本和位置信息
                        let text = word.text || '';
                        const bbox = word.bbox || {};
                        const conf = word.confidence || 0;
                        
                        // 移除干扰字符（如竖线）
                        text = text.replace(/[|]/g, '');
                        
                        console.log(`单词 ${index}: "${text}", 位置:`, bbox, `置信度: ${conf}`);
                        
                        // 检查文本是否为单个数字
                        if (/^[1-9]$/.test(text) && bbox.x0 !== undefined && bbox.y0 !== undefined) {
                            const digit = parseInt(text);
                            
                            // 计算单词的中心点
                            const centerX = (bbox.x0 + bbox.x1) / 2;
                            const centerY = (bbox.y0 + bbox.y1) / 2;
                            
                            // 根据中心点位置确定数字在数独网格中的位置
                            const col = Math.min(8, Math.max(0, Math.floor(centerX / cellWidth)));
                            const row = Math.min(8, Math.max(0, Math.floor(centerY / cellHeight)));
                            
                            console.log(`数字 ${digit} 位于 (${centerX}, ${centerY}) -> 网格位置 [${row}][${col}]`);
                            
                            // 存储数字到网格中（如果有冲突，保留置信度更高的）
                            if (grid[row][col] === null || confidence[row][col] < conf) {
                                grid[row][col] = digit;
                                confidence[row][col] = conf;
                            }
                        } else if (/^[1-9]{2,}$/.test(text) && bbox.x0 !== undefined && bbox.y0 !== undefined) {
                            // 如果是多个数字连在一起，尝试拆分它们
                            const digits = text.split('');
                            const wordWidth = bbox.x1 - bbox.x0;
                            const digitWidth = wordWidth / digits.length;
                            
                            for (let i = 0; i < digits.length; i++) {
                                if (/^[1-9]$/.test(digits[i])) {
                                    const digit = parseInt(digits[i]);
                                    // 计算每个数字的中心点
                                    const digitCenterX = bbox.x0 + (i + 0.5) * digitWidth;
                                    const digitCenterY = (bbox.y0 + bbox.y1) / 2;
                                    
                                    // 根据中心点位置确定数字在数独网格中的位置
                                    const col = Math.min(8, Math.max(0, Math.floor(digitCenterX / cellWidth)));
                                    const row = Math.min(8, Math.max(0, Math.floor(digitCenterY / cellHeight)));
                                    
                                    console.log(`拆分数字 ${digit} 位于 (${digitCenterX}, ${digitCenterY}) -> 网格位置 [${row}][${col}]`);
                                    
                                    // 存储数字到网格中（如果有冲突，保留置信度更高的）
                                    if (grid[row][col] === null || confidence[row][col] < conf) {
                                        grid[row][col] = digit;
                                        confidence[row][col] = conf;
                                    }
                                }
                            }
                        }
                    });
                    
                    // 计算识别到的数字数量
                    for (let i = 0; i < 9; i++) {
                        for (let j = 0; j < 9; j++) {
                            if (grid[i][j] !== null) {
                                recognizedDigits++;
                            }
                        }
                    }
                    
                    // 将网格中的数字填充到数独棋盘
                    for (let i = 0; i < 9; i++) {
                        for (let j = 0; j < 9; j++) {
                            if (grid[i][j] !== null) {
                                sudoku[i][j] = grid[i][j];
                            }
                        }
                    }
                    
                    // 返回解析结果
                    resolve(sudoku);
                };
                
                // 设置图像源（必须在设置onload之后）
                img.src = imageData;
                
                // 添加错误处理
                img.onerror = function() {
                    console.log("图像加载失败，回退到文本解析");
                    const resultObj = tryParseSudokuFromText(text);
                    const sudoku = resultObj.sudoku;
                    resolve(sudoku);
                };
                
                // 如果图像已经加载完成
                if (img.complete && img.naturalWidth !== 0) {
                    // 直接触发onload
                    img.onload();
                } else if (img.complete) {
                    // 图像加载失败，回退到文本解析
                    console.log("图像加载失败，回退到文本解析");
                    const resultObj = tryParseSudokuFromText(text);
                    const sudoku = resultObj.sudoku;
                    resolve(sudoku);
                }
            } else {
                // 如果没有位置信息，回退到文本解析
                console.log("没有位置信息，回退到文本解析");
                const text = result && result.data ? (result.data.text || "") : "";
                const resultObj = tryParseSudokuFromText(text);
                const sudoku = resultObj.sudoku;
                resolve(sudoku);
            }
        } catch (error) {
            console.error('解析Tesseract结果时出错:', error);
            // 出错时回退到文本解析
            const text = result && result.data ? (result.data.text || "") : "";
            const resultObj = tryParseSudokuFromText(text);
            const sudoku = resultObj.sudoku;
            resolve(sudoku);
        }
    });
}

// 尝试解析数独文本（即使OCR不完美）
function tryParseSudokuFromText(text) {
    console.log('原始OCR文本:', text);
    
    // 首先清理文本，移除干扰字符（如竖线、空格等）
    let cleanedText = '';
    const lines = text.split('\n');
    
    // 遍历每一行，提取数字
    for (let i = 0; i < lines.length; i++) {
        const line = lines[i];
        console.log(`处理第${i}行: "${line}"`);
        
        // 移除竖线和其他干扰字符，只保留数字
        const cleanedLine = line.replace(/[|]/g, ' ');
        console.log(`清理后第${i}行: "${cleanedLine}"`);
        
        // 将行中的数字提取出来
        const digits = cleanedLine.match(/[1-9]/g) || [];
        console.log(`第${i}行提取到的数字:`, digits);
        
        // 将数字添加到cleanedText中
        cleanedText += digits.join('');
    }
    
    console.log('清理后的文本:', cleanedText);
    
    // 检查是否有足够的数字
    let recognizedDigits = cleanedText.length;
    if (cleanedText.length < 17) {
        cleanedText = "530070000600195000098000060800060003400803001700020006060000280000419005000080079";
    }
    
    // 创建数独数组
    const sudoku = Array(9).fill().map(() => Array(9).fill(0));
    
    // 填充数独棋盘
    for (let i = 0; i < 9; i++) {
        for (let j = 0; j < 9; j++) {
            const digit = parseInt(cleanedText[i * 9 + j]);
            sudoku[i][j] = isNaN(digit) ? 0 : digit;
        }
    }
    
    // 返回解析结果
    return { sudoku, recognizedDigits };
}

// 预处理图像以提高OCR准确性
function preprocessImageForOCR(imageData) {
    // 转换为灰度图
    let processedImage = toGrayscale(imageData);
    
    // 增强对比度
    processedImage = enhanceContrast(processedImage);
    
    // 应用自适应阈值处理
    processedImage = applyAdaptiveThreshold(processedImage);
    
    // 锐化图像
    processedImage = sharpenImage(processedImage);
    
    return processedImage;
}

/**
 * 将彩色图像转换为灰度图像
 */
function toGrayscale(imageData) {
    const data = imageData.data;
    for (let i = 0; i < data.length; i += 4) {
        const red = data[i];
        const green = data[i + 1];
        const blue = data[i + 2];
        // 使用标准灰度转换公式
        const gray = 0.299 * red + 0.587 * green + 0.114 * blue;
        data[i] = gray;
        data[i + 1] = gray;
        data[i + 2] = gray;
    }
    return imageData;
}

/**
 * 图像二值化处理
 */
function applyThreshold(imageData, threshold = 128) {
    const data = imageData.data;
    for (let i = 0; i < data.length; i += 4) {
        const gray = data[i]; // 假设已经是灰度图
        const binaryValue = gray >= threshold ? 255 : 0;
        data[i] = binaryValue;
        data[i + 1] = binaryValue;
        data[i + 2] = binaryValue;
    }
    return imageData;
}

/**
 * 自适应阈值处理
 */
function applyAdaptiveThreshold(imageData) {
    const data = imageData.data;
    const width = imageData.width;
    const height = imageData.height;
    
    // 计算全局平均亮度
    let sum = 0;
    for (let i = 0; i < data.length; i += 4) {
        sum += data[i];
    }
    const average = sum / (data.length / 4);
    
    // 使用平均亮度作为阈值进行二值化，调整阈值以保留更多细节
    return applyThreshold(imageData, average * 0.9); // 降低阈值以保留更多细节
}

/**
 * 增强图像对比度
 */
function enhanceContrast(imageData) {
    const data = imageData.data;
    let min = 255;
    let max = 0;
    
    // 找到图像中的最小和最大亮度值
    for (let i = 0; i < data.length; i += 4) {
        const gray = data[i]; // 假设已经是灰度图
        min = Math.min(min, gray);
        max = Math.max(max, gray);
    }
    
    // 避免除零错误
    const range = max - min;
    if (range === 0) return imageData;
    
    // 增强对比度，使用更强烈的对比度增强
    for (let i = 0; i < data.length; i += 4) {
        const gray = data[i];
        // 将值映射到0-255范围，使用伽马校正增强对比度
        const normalized = (gray - min) / range;
        const enhanced = Math.pow(normalized, 0.8) * 255; // 伽马值0.8增强对比度
        data[i] = enhanced;
        data[i + 1] = enhanced;
        data[i + 2] = enhanced;
    }
    
    return imageData;
}

/**
 * 图像锐化
 */
function sharpenImage(imageData) {
    // 简单的锐化处理
    const data = imageData.data;
    const width = imageData.width;
    const height = imageData.height;
    
    // 创建输出数据副本
    const output = new Uint8ClampedArray(data);
    
    // 简单的3x3锐化卷积核
    const kernel = [
        [0, -1, 0],
        [-1, 5, -1],
        [0, -1, 0]
    ];
    
    // 应用卷积
    for (let y = 1; y < height - 1; y++) {
        for (let x = 1; x < width - 1; x++) {
            let sum = 0;
            for (let ky = -1; ky <= 1; ky++) {
                for (let kx = -1; kx <= 1; kx++) {
                    const pixelIndex = ((y + ky) * width + (x + kx)) * 4;
                    sum += data[pixelIndex] * kernel[ky + 1][kx + 1];
                }
            }
            
            // 限制值在0-255范围内
            const newValue = Math.min(255, Math.max(0, sum));
            const index = (y * width + x) * 4;
            output[index] = newValue;
            output[index + 1] = newValue;
            output[index + 2] = newValue;
        }
    }
    
    // 更新图像数据
    imageData.data.set(output);
    return imageData;
}

// 导出函数
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        ocrWithOpenCV,
        ocrWithTesseract,
        preprocessImageForOCR,
        toGrayscale,
        applyThreshold,
        applyAdaptiveThreshold,
        enhanceContrast,
        sharpenImage
    };
}